package com.neouton.crm.pm.service.impl;

import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.neouton.common.entity.ActivitiVO;
import com.neouton.common.util.*;
import com.neouton.crm.approval.entity.ApprovalVO;
import com.neouton.crm.approval.service.IApprovalService;
import com.neouton.crm.dictionary.entity.DictionaryLookupItemVO;
import com.neouton.crm.dictionary.service.IDictionaryService;
import com.neouton.crm.entity.SysUserEntity;
import com.neouton.crm.pm.entity.BackMoneyPlanBackEntity;
import com.neouton.crm.pm.entity.BackMoneyPlanVo;
import com.neouton.crm.pm.entity.BackMoneyRecordVo;
import com.neouton.crm.pm.entity.ContractInfoVO;
import com.neouton.crm.pm.mapper.BrAndBmrMapper;
import com.neouton.crm.pm.mapper.ContractInfoMapper;
import com.neouton.crm.pm.service.IContractInfoService;
import com.neouton.crm.prm.entity.ProjectReturnedMoneyVO;
import com.neouton.crm.prm.service.impl.ProjectReturnedMoneyServiceImpl;
import com.neouton.crm.sales.entity.SalesChangeVO;
import com.neouton.crm.sales.mapper.SalesChangeMapper;
import com.neouton.crm.screen.Hander.MapResultHandler;
import com.neouton.crm.transpondEmail.service.TranspondEmailService;
import com.neouton.feginClient.FeginService;
import com.neouton.feginClient.WorkFlowFeginService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 合同相关Service
 * @Author libingkun
 * @Date 2022年11月30日
 * @Version 1.0
 *          初始化迁移
 */
@Service
public class ContractInfoServiceImpl implements IContractInfoService {

    @Resource
    private WorkFlowFeginService workFlowFeginService;

    @Resource
    private ContractInfoMapper contractInfoMapper;

    @Resource
    SalesChangeMapper salesChangeMapper;

    @Resource
    private SalesChangeMapper changeMapper;

    @Resource
    private IDictionaryService dictionaryService;

    @Resource
    private BrAndBmrMapper brAndBmrMapper;

    @Resource
    private ProjectReturnedMoneyServiceImpl returnedMoneyService;

    @Resource
    private IApprovalService approvalService;

    @Resource
    FeginService feginService;

    @Resource
    private TranspondEmailService transpondEmailService;

    @Value("${webSit.web}")
    private String webSitUrl;

    /**
     * 保存合同信息
     * @param contractInfo
     * @return
     */
    @Transactional
    public Integer saveOrUpdateContractInfo(ContractInfoVO contractInfo,String token){
        //1.发起工作流
        //1）获取下一审批人，暂定总经理
        //获取审批人
        SysUserEntity user = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
        //获取人员信息
        Integer businessId = this.startContractApproval();
        //2.记录本地审批数据
        //生成审批主表信息，日志信息
        ApprovalVO approval = approvalService.initApprovalAndLog(businessId, 22, contractInfo.getAskReason(),
                "", -1,"");
        //之后更新/保存
        contractInfo.setApprovalId(approval.getApprovalId());

        //保存，更新合同信息
        if( null == contractInfo.getContractId() ){
            contractInfo.setContractNo(contractInfo.getContractNo().replace("...",this.getContractMaxNumByDate()));
            contractInfoMapper.saveContractInfo(contractInfo);
            //保存回款计划
            saveBackMoneyPlan(contractInfo);
            ProjectReturnedMoneyVO entity = new ProjectReturnedMoneyVO();
            entity.setProjectReturnedMoneyId(contractInfo.getContractId());
            List<ProjectReturnedMoneyVO> voList = returnedMoneyService.queryReturnedMoneyList(entity);
            if (!voList.isEmpty()) {        //更改消息提醒
                returnedMoneyService.updateMessageFlagByList(voList);
            }
        }else {
            ContractInfoVO oldParam = contractInfoMapper.queryContractInfoById(contractInfo.getContractId());
            contractInfoMapper.backUpContractInfo(contractInfo.getContractId(), AuthUtils.getUserId());
            contractInfoMapper.updateContractInfo(contractInfo);
            SalesChangeVO contractInfoChange = new SalesChangeVO();
            contractInfoChange.setSalesRelationId(contractInfo.getContractId());
            contractInfoChange.setChangeClass(3);
            StringBuffer sb = new StringBuffer();
            sb.append(AuthUtils.getUserName()+"将")
                    .append(compare("合同联系人",oldParam.getContractContacts(),contractInfo.getContractContacts()))
                    .append(compare("联系人方式",oldParam.getContractContactsPhone(),contractInfo.getContractContactsPhone()))
                    .append(compare("收货地址",oldParam.getContractShippingAddress(),contractInfo.getContractShippingAddress()))
                    .append(compare("备注",oldParam.getContractRemarks(),contractInfo.getContractRemarks()));
            if (sb.toString().indexOf("将") + 1 != sb.length()) {
                sb.replace(sb.length() - 1,sb.length(), "");
                contractInfoChange.setChangeInfo(sb.toString());
                salesChangeMapper.insert(contractInfoChange);
            }
            ProjectReturnedMoneyVO entity = new ProjectReturnedMoneyVO();
            entity.setProjectReturnedMoneyId(contractInfo.getContractId());
            List<ProjectReturnedMoneyVO> oldList = returnedMoneyService.queryReturnedMoneyList(entity);
            if (!oldList.isEmpty()) {        //更改消息提醒
                returnedMoneyService.updateMessageFlagByList(oldList);
            }
            //修改回款计划
            updateBackMoneyPlan(contractInfo);
            List<ProjectReturnedMoneyVO> newList = returnedMoneyService.queryReturnedMoneyList(entity);
            if (!newList.isEmpty()) {        //更改消息提醒
                returnedMoneyService.updateMessageFlagByList(newList);
            }
        }
        //保存转发人
        transpondEmailService.insertTranspondEmailInfoByUser(contractInfo.getApprovalId(),contractInfo.getForwardUsers());
        if(AuthUtils.getUserAccount().equals(user.getAccount())){
            //跳过第一步审批
            this.approveContractInfo(contractInfo,token,true);
        }else {
//            //发送审批邮件
//            //发送邮件
//            String titel = "【系统通知】合同信息 - 流程单审批通知";
//            String msg =  "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
//                    "<div><p style='text-indent: 2em'>您好，您有一张新的合同审批需要处理：</p></div>"+
//                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
//                    "<div><p style='text-indent: 2em'>申请人："+ AuthUtils.getUserName() + " / " + AuthUtils.getUserAccount() + "</p></div>"+
//                    "<div><p style='text-indent: 2em'>申请原因："+(StringUtils.isEmpty(contractInfo.getAskReason()) ? "无":contractInfo.getAskReason()) + "</p></div>"+
//                    "<div><p style='text-indent: 2em'>申请时间："+DateUtils.getCurrentTime()+"</p></div>"+
//                    "<div><p style='text-indent: 2em'>合同名称："+contractInfo.getContractTopic()+"</p></div>"+
//                    "<div><p style='text-indent: 2em'>合同编号："+contractInfo.getContractNo()+"</p></div>"+
//                    "<div><p style='text-indent: 2em'>合同金额："+contractInfo.getContractAmount()+"元</p></div>"+
//                    "<div><p style='text-indent: 2em'>回款期次：共"+contractInfo.getBmpPeriod()+"期</p></div>"+
//                    "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
//                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
//                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
//                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
//            CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(user.getEmail(),null,titel,msg,token));
            //调用通知接口生成待办通知
            Integer userId = AuthUtils.getUserId();
            CompletableFuture.runAsync(() -> NoticUtils.pushNotic(approval.getApprovalId(), new Timestamp(System.currentTimeMillis()),
                    userId,0,22,user.getUserId(),token));
            approvalService.updateNextApproverByApprovalId(user.getUserId(),contractInfo.getApprovalId());
        }
        return contractInfo.getContractId();
    }

    //保存回款计划
    private void saveBackMoneyPlan(ContractInfoVO contractInfo) {

        List<BackMoneyPlanVo> backMoneyPlanList = contractInfo.getBackMoneyPlanList();
        for (BackMoneyPlanVo backMoneyPlanVo : backMoneyPlanList) {
            backMoneyPlanVo.setProjectManageId(contractInfo.getProjectManageId());
            backMoneyPlanVo.setContractId(contractInfo.getContractId());
            backMoneyPlanVo.setIsBm(0);
        }
        contractInfoMapper.saveBackMoneyPlan(backMoneyPlanList);
    }
    //修改回款计划
    private void updateBackMoneyPlan(ContractInfoVO contractInfo) {
        //在回款计划备份表中 --保存回款计划
        //根据合同id 查询得到回款计划，将结果写入回款计划备份表中
        List<BackMoneyPlanVo> backMoneyPlanByContractId = brAndBmrMapper.getBackMoneyPlanByContractId(contractInfo.getContractId());
        ArrayList<BackMoneyPlanBackEntity> backMoneyPlanBackEntities = new ArrayList<>();
        for (BackMoneyPlanVo backMoneyPlanVo : backMoneyPlanByContractId) {
            BackMoneyPlanBackEntity backMoneyPlanBackEntity = new BackMoneyPlanBackEntity();
            BeanUtils.copyProperties(backMoneyPlanVo,backMoneyPlanBackEntity);
            backMoneyPlanBackEntity.setApprovalId(contractInfo.getApproval().getApprovalId());
            backMoneyPlanBackEntities.add(backMoneyPlanBackEntity);
        }
        //写入回款计划备份表
        brAndBmrMapper.saveBackMoneyPlanBack(backMoneyPlanBackEntities);

        List<BackMoneyPlanVo> backMoneyPlanList = contractInfo.getBackMoneyPlanList();
        for (BackMoneyPlanVo backMoneyPlanVo : backMoneyPlanList) {
            brAndBmrMapper.deleteBackMoneyPlan(backMoneyPlanVo);
            if(backMoneyPlanVo.getBmpId() != null){
                backMoneyPlanVo.setBmpId(null);
            }else{
                backMoneyPlanVo.setProjectManageId(contractInfo.getProjectManageId());
                backMoneyPlanVo.setContractId(contractInfo.getContractId());
                backMoneyPlanVo.setIsBm(0);
            }
        }
            contractInfoMapper.saveBackMoneyPlan(backMoneyPlanList);
    }

    /**
     * 更具主键获取项目信息
     * @param approvalId 审批主键
     * @return
     */
    public ContractInfoVO queryContractInfoByapprovalId(Integer approvalId){
        ContractInfoVO contractInfo = contractInfoMapper.queryContractInfoByapprovalId(approvalId);
        //保存转发人
        contractInfo.setForwardUsers(transpondEmailService.queryTranspondByApprovalId(approvalId));
        return contractInfo;
    }

    /**
     * 更具主键获取合同历史数据
     * @param approvalId 审批主键
     * @return
     */
    public ContractInfoVO getContractInfoHistoryByApprovalId(Integer approvalId){
        ContractInfoVO contractInfo = contractInfoMapper.queryContractInfoHistoryByApprovalId(approvalId);
        if(contractInfo != null){
            //回款计划备份表中查询回款计划信息
            List<BackMoneyPlanBackEntity> backMoneyPlanBackByApprovalId = brAndBmrMapper.getBackMoneyPlanBackByApprovalId(approvalId);
            ArrayList<BackMoneyPlanVo> backMoneyPlanVos = new ArrayList<>();
            for (BackMoneyPlanBackEntity backMoneyPlanBackEntity : backMoneyPlanBackByApprovalId) {
                BackMoneyPlanVo backMoneyPlanVo = new BackMoneyPlanVo();
                BeanUtils.copyProperties(backMoneyPlanBackEntity,backMoneyPlanVo);
                backMoneyPlanVos.add(backMoneyPlanVo);
            }
            contractInfo.setBackMoneyPlanList(backMoneyPlanVos);
        }else {
            contractInfo = contractInfoMapper.queryContractInfoByapprovalId(approvalId);
            //回款计划表中查询回款计划信息
            contractInfo.setBackMoneyPlanList(brAndBmrMapper.getBackMoneyPlanByContractId(contractInfo.getContractId()));
        }
        contractInfo.setForwardUsers(transpondEmailService.queryTranspondByApprovalId(approvalId));
        return contractInfo;
    }

    /**
     * 更具主键获取合同信息
     * @param ContractId
     * @return
     */
    public ContractInfoVO queryContractInfoById(Integer ContractId){
        ContractInfoVO contractInfo = contractInfoMapper.queryContractInfoById(ContractId);
        //保存转发人
        contractInfo.setForwardUsers(transpondEmailService.queryTranspondByApprovalId(contractInfo.getApproval().getApprovalId()));
        return contractInfo;
    }


    /**
     * 更具项目ID获取合同信息
     * @param projectId
     * @return
     */
    public List<ContractInfoVO> queryContractInfoByProjectId(Integer projectId,String callWms){
        return contractInfoMapper.queryContractInfoByProjectId(projectId,callWms);
    }

    /**
     * 获取当日最大合同单号
     * @return
     */
    public String getContractMaxNumByDate(){
        Integer num = contractInfoMapper.getContractMaxNumByDate();
        if(num<10)
            return "0"+num;
        else
            return num.toString();
    }

    private String compare(String pre, String oldValue, String newValue) {
        if (!Objects.equals(oldValue, newValue)) {
            return pre + "从：" + oldValue + "变更：" + newValue + "，";
        }
        return "";
    }

    /**
     * 获取变更记录
     * @param contractInfoId
     * @return
     */
    public List<SalesChangeVO> queryChangeInfo(Integer contractInfoId){
        return changeMapper.queryChangeInfo(contractInfoId, Constants.CONTRACT_MODEL_ID);
    }

    /**
     * 保存回款计划
     * @param backMoneyPlanList
     */
    @Override
    public void saveBackMoneyPlan(List<BackMoneyPlanVo> backMoneyPlanList) {
        for (BackMoneyPlanVo backMoneyPlanVo : backMoneyPlanList) {
            backMoneyPlanVo.setIsBm(0);
            backMoneyPlanVo.setIsBilling(0);
        }
        contractInfoMapper.saveBackMoneyPlan(backMoneyPlanList);
    }

    /**
     * 根据合同id查询得到回款计划内容
     * @param id
     * @return
     */
    @Override
    public List<BackMoneyPlanVo> searchBackMoneyPlanBycontractId(Integer id) {
        return contractInfoMapper.searchBackMoneyPlanBycontractId(id);
    }

    /**
     * 根据合同id查询得到回款计划内容
     * @param id
     * @return
     */
    public BackMoneyPlanVo searchBackMoneyPlanByBmpId(Integer id){
        return contractInfoMapper.searchBackMoneyPlanByBmpId(id);
    }


    /**
     * 合同信息驳回审批
     * @param contractInfo
     * @return
     */
    @Transactional
    public Boolean rejectionContractInfo(ContractInfoVO contractInfo,String token){
        //获取工作流ID
        ApprovalVO approval = approvalService.queryApprovalByAppID(contractInfo.getApprovalId());

        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setBusinessId(approval.getBusinessId());
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
//        //获取当前所处节点
//        ResponseAPI<ActivitiVO> processNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);
        //删除流程实例
        workFlowFeginService.deleteInstance(activitiVO);
        //驳回至上一节点
//        workFlowFeginService.rejectedByBusinessId(activitiVO);
        SysUserEntity user = null;
        Integer workState;
        String titel;
        String msg;
        Integer todoUser;
        SysUserEntity askUser = feginService.searchUserInfoById(approval.getCreator(), token).getResult();
//        if( "商务审批".equals(processNodeNameAndCode.getResult().getName()) ){
            user = askUser;
            //驳回至起点
            workState = 1;
            titel= "【系统通知】合同信息 - 流程单审批驳回通知";
            msg =  "<div><p >" + "尊敬的" + askUser.getLoginName() + "：</p></div>" +
                "<div><p style='text-indent: 2em'>您好，您申请的合同审批已被驳回：</p></div>"+
                "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                "<div><p style='text-indent: 2em'>审批人："+AuthUtils.getUserName() + " / " + AuthUtils.getUserAccount() +"</p></div>"+
                "<div><p style='text-indent: 2em'>审批意见："+(StringUtils.isEmpty(contractInfo.getAppReason()) ? "无":contractInfo.getAppReason()) +"</p></div>"+
                "<div><p style='text-indent: 2em'>审批时间："+DateUtils.getCurrentTime()+"</p></div>"+
                "<div><p style='text-indent: 2em'>合同名称："+contractInfo.getContractTopic()+"</p></div>"+
                "<div><p style='text-indent: 2em'>合同编号："+contractInfo.getContractNo()+"</p></div>"+
                "<div><p style='text-indent: 2em'>合同金额："+contractInfo.getContractAmount()+"元</p></div>"+
                "<div><p style='text-indent: 2em'>回款期次：共"+contractInfo.getBmpPeriod()+"期</p></div>"+
                "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 项目信息管理 - 项目信息 " +
                "<a href='"+webSitUrl+"/?m=crm&p=projectmanage&me=projectmanageInfo'>进入</a></p></div>"+
                "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
            approvalService.approvalRejection(null,contractInfo.getApprovalId());
            todoUser = 0;
//        }else {
//            if("财务审批".equals(processNodeNameAndCode.getResult().getName())){
//                user = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
//            }else if("售后审批".equals(processNodeNameAndCode.getResult().getName())){
//                user = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
//            }else if("总经理审批".equals(processNodeNameAndCode.getResult().getName())){
//                user = dictionaryService.queryMenuUserIdsByCode("afterSales").get(0);
//            }
//            workState = 0;
//            titel = "【系统通知】合同信息审批待处理通知";
//            msg =  initContractEmailData(user.getLoginName(),"您有一张新的合同审批已被上级驳回，需要处理"
//                    ,approval.getApprovalCode(), askUser.getLoginName(),contractInfo.getContractTopic(),contractInfo.getContractNo(),contractInfo.getContractAmount(),
//                    contractInfo.getBmpPeriod());
//            todoUser = user.getUserId();
//            approvalService.updateNextApproverByApprovalId(user.getUserId(),contractInfo.getApprovalId());
//        }
        //记录日志
        approvalService.insertApprovalLog(approval.getApprovalId(),"驳回",
                "",contractInfo.getAppReason());
        SysUserEntity finalUser = user;
        CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(),null,titel,msg,token));
        CompletableFuture.runAsync(() -> NoticUtils.pushNotic(contractInfo.getApprovalId(),  approval.getCreateDataTime(),
                approval.getCreator(),workState,22,todoUser,token));
        return true;
    }

    /**
     * 合同信息通过审批
     * @param contractInfo
     * @return
     */
    @Transactional
    public Boolean approveContractInfo(ContractInfoVO contractInfo,String token,Boolean auto){
        //获取工作流ID
        ApprovalVO approval = approvalService.queryApprovalByAppID(contractInfo.getApprovalId());
        ActivitiVO activitiVO = new ActivitiVO();//最终审批人
        activitiVO.setBusinessId(approval.getBusinessId());
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        //获取当前所处节点
        ResponseAPI<ActivitiVO> processNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);
        SysUserEntity user = null;
        Integer workState;
        String titel;
        String msg;
        Integer todoUser;
        String ccUser = null;
        SysUserEntity askUser = feginService.searchUserInfoById(approval.getCreator(), token).getResult();
        //记录审批日志
        if(auto){
            approvalService.insertApprovalLog(approval.getApprovalId(),"通过",
                    "系统判定跳过",contractInfo.getAppReason());
        }else {
            //记录日志
            approvalService.insertApprovalLog(approval.getApprovalId(),"通过",
                    "",contractInfo.getAppReason());
        }
        if( "售后审批".equals(processNodeNameAndCode.getResult().getName()) ){
            //审批通过
            workFlowFeginService.approvalProcessByBusinessId(activitiVO);
            user=askUser;
            workState = 1;
            todoUser = 0;
            titel = "【系统通知】合同信息 - 流程单审批通过通知";
            msg =  "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
                    "<div><p style='text-indent: 2em'>您好，您申请的合同审批已通过：</p></div>"+
                    "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>合同名称："+contractInfo.getContractTopic()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>合同编号："+contractInfo.getContractNo()+"</p></div>"+
                    "<div><p style='text-indent: 2em'>合同金额："+contractInfo.getContractAmount()+"元</p></div>"+
                    "<div><p style='text-indent: 2em'>回款期次：共"+contractInfo.getBmpPeriod()+"期</p></div>"+
                    "<div><p style='text-indent: 2em'>系统查看路径：客户关系管理系统 - 项目信息管理 - 项目信息 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=projectmanage&me=projectmanageInfo'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
            ccUser = this.queryContractCC();
            approvalService.approved(null,contractInfo.getApprovalId());

            String transpondEmails = transpondEmailService.selectTranspondEmailStr(contractInfo.getApprovalId());
            if(!transpondEmails.isEmpty()){
                ccUser = ccUser + "," + transpondEmails;
            }
            SysUserEntity finalUser = user;
            String finalCcUser = ccUser;
            CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(), finalCcUser,titel,msg,token));
            CompletableFuture.runAsync(() -> NoticUtils.pushNotic(contractInfo.getApprovalId(),  approval.getCreateDataTime(),
                    approval.getCreator(),workState,22,todoUser,token));
        }else {
            //动态获取下一步审批人员以及流程，设置参数
            if("商务审批".equals(processNodeNameAndCode.getResult().getName())){
                user = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
                activitiVO.getCustomParams().put("finance",user.getAccount());
            }else if("财务审批".equals(processNodeNameAndCode.getResult().getName())){
                user = dictionaryService.queryMenuUserIdsByCode("afterSales").get(0);
                activitiVO.getCustomParams().put("afterSales",user.getAccount());
            }
            //审批通过（使用动态入参传入下一审批人）
            workFlowFeginService.approvalProcessCustomUserByBusinessId(activitiVO);
            //获取下一节点
            ResponseAPI<ActivitiVO> nextProcessNodeNameAndCode = workFlowFeginService.getProcessNodeNameAndCode(activitiVO);
            if(nextProcessNodeNameAndCode.getResult().getAssignee().equals(processNodeNameAndCode.getResult().getAssignee())){ //记录日志
                this.approveContractInfo(contractInfo,token,true);
            }else {
                workState = 0;
                todoUser = user.getUserId();
                //交由下一审批人处理
//                titel = "【系统通知】合同信息 - 流程单审批通知";
//                msg =   "<div><p >" + "尊敬的" + user.getLoginName() + "：</p></div>" +
//                        "<div><p style='text-indent: 2em'>您好，您有一张新的合同审批需要处理：</p></div>"+
//                        "<div><p style='text-indent: 2em'>事项编号："+approval.getApprovalCode()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请人："+ AuthUtils.getUserName() + " / " + AuthUtils.getUserAccount() + "</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请原因："+(StringUtils.isEmpty(contractInfo.getAskReason()) ? "无":contractInfo.getAskReason())+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>申请时间："+DateUtils.getCurrentTime()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>合同名称："+contractInfo.getContractTopic()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>合同编号："+contractInfo.getContractNo()+"</p></div>"+
//                        "<div><p style='text-indent: 2em'>合同金额："+contractInfo.getContractAmount()+"元</p></div>"+
//                        "<div><p style='text-indent: 2em'>回款期次：共"+contractInfo.getBmpPeriod()+"期</p></div>" +
//                        "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
//                        "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
//                        "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
//                        "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
//                String finalCcUser = ccUser;
//                SysUserEntity finalUser = user;
//                CompletableFuture.runAsync(() -> EmailUtils.sentMailByAddressee(finalUser.getEmail(), finalCcUser,titel,msg,token));
                approvalService.updateNextApproverByApprovalId(user.getUserId(),contractInfo.getApprovalId());
                CompletableFuture.runAsync(() -> NoticUtils.pushNotic(contractInfo.getApprovalId(),  approval.getCreateDataTime(),
                        approval.getCreator(),workState,22,todoUser,token));
            }
        }
        return true;
    }

    /**
     * 获取合同抄送人
     * @return
     */
    private String queryContractCC(){
        //获取抄送人
        List<SysUserEntity> userIds = dictionaryService.queryCcUserIdsByCode("contractCC");
        StringBuilder emailList = new StringBuilder();
        for (int i = 0; i < userIds.size(); i++) {
            if (userIds.size()-1 == i){
                emailList.append(userIds.get(i).getEmail());
            }else {
                emailList.append(userIds.get(i).getEmail());
                emailList.append(",");
            }
        }
        return emailList.toString();
    }

    /**
     * 开启审批流程
     * @return
     */
    private Integer startContractApproval(){
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        activitiVO.setProcessName("合同审批");
        activitiVO.setProcessCode("contract_approval");
//        activitiVO.setVersion("1");
        activitiVO.setNextNodeParams("commercialSpecialist");
//        HashMap<String,Object> customParams = new HashMap<>();
        //商务负责人
        SysUserEntity business = dictionaryService.queryMenuUserIdsByCode("commercialSpecialist").get(0);
        activitiVO.setNextNodeAssignee(business.getAccount());

//        customParams.put("commercialSpecialist",business.getAccount());
//        //财务负责人
//        SysUserEntity finance = dictionaryService.queryMenuUserIdsByCode("finance").get(0);
//        customParams.put("finance",finance.getAccount());
//        //售后负责人
//        SysUserEntity afterSales = dictionaryService.queryMenuUserIdsByCode("afterSales").get(0);
//        customParams.put("afterSales",afterSales.getAccount());
//        //总经理
//        SysUserEntity president = dictionaryService.queryMenuUserIdsByCode("president").get(0);
//        customParams.put("president",president.getAccount());
//        activitiVO.setCustomParams(customParams);
        ResponseAPI<ActivitiVO> responseAPI = workFlowFeginService.startMaxVersionProcessByDesignCodeCustomParams(activitiVO);
        return responseAPI.getResult().getBusinessId();
    }

    /**
     * 生成邮件内容
     * @param userName 邮件发送人
     * @param msgTopic 邮件主题
     * @param approvalCode 事项编号
     * @param askeUserName 申请人
     * @param contractTopic 合同名称
     * @param contractNo 合同号
     * @param contractAmount 合同金额
     * @param bmpPeriod 回款期次
     * @return
     */
    private String initContractEmailData(String userName,String msgTopic,String approvalCode,String askeUserName,
                                         String contractTopic, String contractNo,
                                         String contractAmount,Integer bmpPeriod){
        String msg =  "<div><p >" + "尊敬的" + userName + "：</p></div>" +
        "<div><p style='text-indent: 2em'>您好，"+msgTopic +"：</p></div>"+
        "<div><p style='text-indent: 2em'>事项编号："+approvalCode+"</p></div>"+
        "<div><p style='text-indent: 2em'>申请人："+askeUserName+"</p></div>"+
        "<div><p style='text-indent: 2em'>合同名称："+contractTopic+"</p></div>"+
        "<div><p style='text-indent: 2em'>合同编号："+contractNo+"</p></div>"+
        "<div><p style='text-indent: 2em'>合同金额："+contractAmount+"元</p></div>"+
        "<div><p style='text-indent: 2em'>回款期次：共"+bmpPeriod+"期</p></div>";

        if(msgTopic.contains("处理")){
            msg += "<div><p style='text-indent: 2em'>系统审批路径：客户关系管理系统 - 待办事项 - 待办审批 " +
                    "<a href='"+webSitUrl+"/?m=crm&p=crmtodoItems&me=todoApprovalPath'>进入</a></p></div>"+
                    "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        }else {
            msg += "<div><p style='text-indent: 2em'>谢谢！</p></div>"+
                    "<div><p style='text-indent: 2em'>说明：该邮件为系统自动发送，请勿回复。</p></div>";
        }
        return msg;
    }

    /**
     * 通过项目ID查询目前项目下 审批中或审批通过的合同总金额
     * @param projectId 项目ID
     * @return
     */
    public BigDecimal queryConMoneyByProjectId(Integer projectId){
        return contractInfoMapper.queryConMoneyByProjectId(projectId);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param entity
     * @return
     */
    public PageUtil<ContractInfoVO> queryContractsByPage(IPage page, ContractInfoVO entity,String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"contractInfo", token);
        IPage<ContractInfoVO> iPage = contractInfoMapper.queryContractsByPage(page, entity,userList);
        List<ContractInfoVO> list = iPage.getRecords();
        if(!list.isEmpty()){
            BigDecimal contractAmountPage = new BigDecimal("0");
            BigDecimal billMoneyPage = new BigDecimal("0");
            BigDecimal bmrMoneyPage = new BigDecimal("0");
            for (ContractInfoVO cVo: list) {
                contractAmountPage = contractAmountPage.add(new BigDecimal(cVo.getContractAmount()));
                billMoneyPage = billMoneyPage.add(cVo.getBillMoneys());
                bmrMoneyPage = bmrMoneyPage.add(cVo.getBmrMoneys());
            }
            list.get(0).setContractAmountPage(String.valueOf(contractAmountPage));
            list.get(0).setBillMoneyPage(String.valueOf(billMoneyPage));
            list.get(0).setBmrMoneyPage(String.valueOf(bmrMoneyPage));
            iPage.setRecords(list);
        }

        return new PageUtil(iPage);
    }


    public List<SysUserEntity> queryUserList(Integer userId,String authCode, String token) {
        List<SysUserEntity> userList = new ArrayList<>();
        List<SysUserEntity> authUserIList = dictionaryService.queryAuthUserIdsByCode(authCode);
        boolean result = false;
        for (SysUserEntity user:authUserIList) {
            if (Objects.equals(user.getUserId(), userId)) {
                result = true;
            }
        }
        if (result) {
            userList = feginService.getUserIgnoreFlag(token).getResult();
        } else {
            SysUserEntity user = feginService.searchUserInfoByIds(userId,token).getResult();
            if (user.getIsLeader() == 1) {
                userList = feginService.recursiveQueryAllUserByLeaderId(userId, token).getResult();
            }
            userList.add(user);
        }
        return userList;
    }

    /**
     * 一指禅系统产品列表导出
     *
     * @param response
     */
    public void exportContractInfo(HttpServletResponse response, ContractInfoVO entit, String token) throws Exception{
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"contractInfo", token);
        List<ContractInfoVO> contractInfos = contractInfoMapper.queryAllContractInfos(entit,userList);
        List<String> codes = new ArrayList<>();
        codes.add("paymentPeriod");
        Map<String, List<DictionaryLookupItemVO>> stringListMap = dictionaryService.queryDictionaryLookupInfo(null, codes);
        for (int i = 0; i < contractInfos.size(); i++) {
            ContractInfoVO contractInfo = contractInfos.get(i);
            contractInfo.setContractId(i+1);
            //付款期次
            for(DictionaryLookupItemVO dictionaryLookupItemVO : stringListMap.get("paymentPeriod") ){
                if(dictionaryLookupItemVO.getItemCode().equals(contractInfo.getBmpPeriod()+"")){
                    contractInfo.setBmpPeriodStr(dictionaryLookupItemVO.getItemName());
                    break;
                }
            }
            if(1 == contractInfo.getContractType()){
                contractInfo.setContractTypeStr("中标合同");
            }else {
                contractInfo.setContractTypeStr("自有合同");
            }

            if(0 == contractInfo.getApproval().getApprovalStatus()){
                contractInfo.setApprovalStr("审批中");
            }else if(1 == contractInfo.getApproval().getApprovalStatus()){
                contractInfo.setApprovalStr("已通过");
            }else if(2 == contractInfo.getApproval().getApprovalStatus()){
                contractInfo.setApprovalStr("已驳回");
            }else if(3 == contractInfo.getApproval().getApprovalStatus()){
                contractInfo.setApprovalStr("已撤回");
            }else if(5 == contractInfo.getApproval().getApprovalStatus()){
                contractInfo.setApprovalStr("撤回中");
            }
            contractInfo.setContractSigningDateStr(String.format("%tY-%<tm-%<td",contractInfo.getContractSigningDate()));
        }

        //获取yml模板位置
        YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
        String path = "application.yml";
        factoryBean.setResources(new ClassPathResource(path));
        Properties properties = factoryBean.getObject();
        String contractTemplatePath = String.valueOf(properties.get("report.contractTemplate"));

        //依据根目录获取模板位置
        TemplateExportParams params = new TemplateExportParams(contractTemplatePath);
        Map<String, Object> map = new HashMap<>();
        map.put("contractInfos",contractInfos);
        ReportUtils.exportExcel(params,map,"合同列表",response);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param entity
     * @return
     */
    public PageUtil<BackMoneyPlanVo> queryBackMoneyPlansByPage(IPage page, BackMoneyPlanVo entity,String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"backMoneyPlans", token);
        return new PageUtil(contractInfoMapper.queryBackMoneyPlansByPage(page, entity,userList));
    }

    /**
     * 更据采合同ID获取合同相关回款 开票记录数据
     * @param conId
     * @return
     */
    public Map<String,BigDecimal> queryPurBackInfoByConId(int conId){
        MapResultHandler<String, BigDecimal> resultHandler = new MapResultHandler<>();
        contractInfoMapper.queryPurBackInfoByConId(resultHandler,conId);
        Map<String, BigDecimal> results = resultHandler.getMappedResults();
        //采购未付款金额 采购总金额-已付款金额
        results.put("未回总额", results.get("合同总额").subtract(results.get("已回总额")).setScale(2, RoundingMode.HALF_DOWN));
        return results;
    }

    /**
     * 回款计划列表导出
     *
     * @param response
     */
    public void exportBackMoneyPlans(HttpServletResponse response, BackMoneyPlanVo entit, String token) throws Exception{
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"backMoneyPlans", token);

        List<BackMoneyPlanVo> backMoneyPlans = contractInfoMapper.queryBackMoneyPlans(entit,userList);
        List<String> codes = new ArrayList<>();
        codes.add("paymentPeriodNum");
        codes.add("isBm");
        codes.add("isBilling");
        Map<String, List<DictionaryLookupItemVO>> stringListMap = dictionaryService.queryDictionaryLookupInfo(null, codes);
        for (int i = 0; i < backMoneyPlans.size(); i++) {
            BackMoneyPlanVo backMoneyPlan = backMoneyPlans.get(i);
            //付款期次
            for(DictionaryLookupItemVO dictionaryLookupItemVO : stringListMap.get("paymentPeriodNum") ){
                if(dictionaryLookupItemVO.getItemCode().equals(backMoneyPlan.getBmpPeriod()+"")){
                    backMoneyPlan.setBmpPeriodStr(dictionaryLookupItemVO.getItemName());
                    break;
                }
            }
            for(DictionaryLookupItemVO dictionaryLookupItemVO : stringListMap.get("isBm") ){
                if(dictionaryLookupItemVO.getItemCode().equals(backMoneyPlan.getIsBm()+"")){
                    backMoneyPlan.setIsBmStr(dictionaryLookupItemVO.getItemName());
                    break;
                }
            }
            for(DictionaryLookupItemVO dictionaryLookupItemVO : stringListMap.get("isBilling") ){
                if(dictionaryLookupItemVO.getItemCode().equals(backMoneyPlan.getIsBilling()+"")){
                    backMoneyPlan.setIsBillingStr(dictionaryLookupItemVO.getItemName());
                    break;
                }
            }

            if(0 == backMoneyPlan.getContractInfo().getApproval().getApprovalStatus()){
                backMoneyPlan.getContractInfo().setApprovalStr("审批中");
            }else if(1 == backMoneyPlan.getContractInfo().getApproval().getApprovalStatus()){
                backMoneyPlan.getContractInfo().setApprovalStr("已通过");
            }else if(2 == backMoneyPlan.getContractInfo().getApproval().getApprovalStatus()){
                backMoneyPlan.getContractInfo().setApprovalStr("已驳回");
            }else if(3 == backMoneyPlan.getContractInfo().getApproval().getApprovalStatus()){
                backMoneyPlan.getContractInfo().setApprovalStr("已撤回");
            }else if(5 == backMoneyPlan.getContractInfo().getApproval().getApprovalStatus()){
                backMoneyPlan.getContractInfo().setApprovalStr("撤回中");
            }
            backMoneyPlan.setBmpDateStr(String.format("%tY-%<tm-%<td",backMoneyPlan.getBmpDate()));
        }

        //获取yml模板位置
        YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
        String path = "application.yml";
        factoryBean.setResources(new ClassPathResource(path));
        Properties properties = factoryBean.getObject();
        String contractTemplatePath = String.valueOf(properties.get("report.backMoneyPlanTemplate"));

        //依据根目录获取模板位置
        TemplateExportParams params = new TemplateExportParams(contractTemplatePath);
        Map<String, Object> map = new HashMap<>();
        map.put("backMoneyPlanInfos",backMoneyPlans);
        ReportUtils.exportExcel(params,map,"回款计划列表",response);
    }

    /**
     * 分页查询待办信息
     *
     * @param page
     * @param entity
     * @return
     */
    public PageUtil<ContractInfoVO> queryApprovalContractByPage(IPage page, ContractInfoVO entity){
        //获取工作流待办
        ActivitiVO activitiVO = new ActivitiVO();
        activitiVO.setAuthorization(AuthUtils.getUserAccount());
        ResponseAPI<List<ActivitiVO>> workFlowVoResponseAPI = workFlowFeginService.getTasksByAuthorization(activitiVO);
        List<ActivitiVO> activitiVOS = workFlowVoResponseAPI.getResult();
        if( activitiVOS == null || activitiVOS.size() == 0 ){
            return new PageUtil(new PageDTO());
        }else{
            return new   PageUtil( contractInfoMapper.queryApprovalContractByPage(page, entity,activitiVOS));
        }
    }

    /**
     * 分页查询已办信息
     *
     * @param page
     * @param entity
     * @return
     */
    public PageUtil<ContractInfoVO> queryApprovalContractDoneByPage(IPage page, ContractInfoVO entity){
        IPage<ContractInfoVO> iPage = contractInfoMapper.queryApprovalContractDoneByPage(page, entity);
        return new PageUtil(iPage);
    }


    /**
     * 分页查询申请记录信息
     *
     * @param page
     * @param entity
     * @return
     */
    public PageUtil<ContractInfoVO> queryApprovalContractRecordByPage(IPage page, ContractInfoVO entity,String token){
        List<SysUserEntity> userList = this.queryUserList(AuthUtils.getUserId(),"approvalRecord", token);
        IPage<ContractInfoVO> iPage = contractInfoMapper.queryApprovalContractRecordByPage(page, entity,userList);
        return new PageUtil(iPage);
    }

    /**
     * 逻辑删除合同信息
     * @param conId
     * @return
     */
    @Override
    public Boolean deleteContractInfoById(Integer conId){
        return contractInfoMapper.deleteContractInfoById(conId);
    }

    @Override
    public void updateContractInfoAfterPass(ContractInfoVO contractInfoVO, String token) {
        // 将修改后的数据放入redis缓存
        Map<String,Object> projectInfoMap = new HashMap<>();
        projectInfoMap.put(contractInfoVO.getContractId().toString(),contractInfoVO);
        feginService.setCacheInfo(Constants.CACHE_CONTRACTINFO + contractInfoVO.getContractId(),projectInfoMap,token);
    }

    @Override
    public ContractInfoVO queryContractInfoFromCache(int contractId, String token) {
        String managerCacheKey = Constants.CACHE_CONTRACTINFO+contractId;
        ResponseAPI cacheInfo = feginService.getCacheInfo(managerCacheKey,String.valueOf(contractId), token);
        String jsonObject= JSON.toJSONString(cacheInfo.getResult());
        //将json转成需要的对象
        ContractInfoVO contractInfoVO = JSONObject.parseObject(jsonObject,ContractInfoVO.class);
        return contractInfoVO;
    }

    @Override
    public List<ContractInfoVO> replaceBackMoneyByContractId(List<ContractInfoVO> contractInfoVOs, String token) {
        for (int i = 0; i < contractInfoVOs.size(); i++) {
            ContractInfoVO replaceAfterUpdate = this.queryContractInfoFromCache(contractInfoVOs.get(i).getContractId(), token);
            if(replaceAfterUpdate!=null){
                contractInfoVOs.set(i,replaceAfterUpdate);
            }
        }
        return contractInfoVOs;
    }
}
